package com.bjsxt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjsxt.domain.AccountDetail;
import com.bjsxt.dto.UserDto;
import com.bjsxt.feign.UserFeignClient;
import com.bjsxt.mapper.AccountDetailMapper;
import com.bjsxt.modle.AccountDetailVo;
import com.bjsxt.service.AccountDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class AccountDetailServiceImpl extends ServiceImpl<AccountDetailMapper, AccountDetail> implements AccountDetailService {
    /**
     * 注入会员用户操作的 openFeign 对象
     */
    @Autowired
    private UserFeignClient userFeignClient;

    /**
     * 根据条件分页查询资金流水记录
     *
     * @param page        分页对象<AccountDetail>
     * @param accountId   账户 ID
     * @param coinId      币种 ID
     * @param userId      用户 ID
     * @param userName    用户名
     * @param mobile      手机号码
     * @param amountStart 最小充值金额
     * @param amountEnd   最大充值金额
     * @param startTime   开始日期
     * @param endTime     结束日期
     * @return 统一响应对象
     */
    @Override
    public Page<AccountDetailVo> pageByAccountIdAndCoinIdAndUserIdAndUserNameAndMobileAndAmountAndCreateTime(Page<AccountDetail> page, Long accountId, Long coinId, Long userId, String userName, String mobile, Integer amountStart, Integer amountEnd, Date startTime, Date endTime) {
        // 查询出的用户数据，用于第一次进行条件的限定查询，三个值都没有则正常的走分页查询，再构建数据，否则则进行先查询 id 再进行数据的拼接，两个条件的限定查询只会走一次
        Map<Long, UserDto> userDtoMap = null;
        // 用户的 id 集合
        Set<Long> ids = null;
        // 判断，三个值有一个有值的情况才进行查询 id
        if (userId != null || !StringUtils.isEmpty(userName) || !StringUtils.isEmpty(mobile)) {
            // 将三个条件传递到会员系统进行查询，返回 map key 就是 id
            userDtoMap = userFeignClient.getBasicUsersMap(userId == null ? null : Collections.singletonList(userId), userName, mobile);
            // 用户 id 集合
            ids = userDtoMap.keySet();
        }
        // 构建查询多条件查询
        QueryWrapper<AccountDetail> queryWrapper = new QueryWrapper<>();
        // 构建查询条件
        queryWrapper.in(ids != null && !ids.isEmpty(), AccountDetail.COL_USER_ID, ids);
        queryWrapper.eq(coinId != null, AccountDetail.COL_COIN_ID, coinId);
        queryWrapper.eq(accountId != null, AccountDetail.COL_ID, accountId);
        queryWrapper.between(amountStart != null && amountEnd != null, AccountDetail.COL_AMOUNT, amountStart, amountEnd);
        queryWrapper.between(startTime != null && endTime != null, AccountDetail.COL_CREATED, startTime, endTime);
        // 调用方法进行数据的查询
        Page<AccountDetail> accountDetailPage = page(page, queryWrapper);
        // 如果在这里进行获取之后是空的没有获取到，那么就需要远程调用方法进行值的获取
        if (userDtoMap == null) {
            // 获取需要查询的 ids 集合
            List<Long> idList = accountDetailPage.getRecords().stream().map(AccountDetail::getUserId).collect(Collectors.toList());
            // 如果擦查询的 idList 是空则直接进行返回
            if (idList.isEmpty()) return new Page<>();
            // 根据 id 集合进行数据的查询
            userDtoMap = userFeignClient.getBasicUsersMap(idList, null, null);
        }
        // 如果擦查询的 userDtoMap 是空则直接进行返回
        if (userDtoMap.isEmpty()) return new Page<>();
        // 因为使用 lambda 表达式，下面这个 map 需要为 final 的
        Map<Long, UserDto> finalUserDtoMap = userDtoMap;
        // 拼接返回的 vo 对象，循环遍历返回的对象
        IPage<AccountDetailVo> accountDetailVoIPage = accountDetailPage.convert(accountDetail -> {
            // 创建转换的 vo 对象
            AccountDetailVo accountDetailVo = new AccountDetailVo();
            // 进行值的 copy
            BeanUtil.copyProperties(accountDetail, accountDetailVo);
            // 获取用户对象
            UserDto userDto = finalUserDtoMap.get(accountDetailVo.getUserId());
            // 查询的数据不为空
            if (userDto != null) {
                // 设置昵称
                accountDetailVo.setUserName(userDto.getUsername());
                // 设置真实姓名
                accountDetailVo.setRealName(userDto.getRealName());
            }
            // 返回 vo 对象
            return accountDetailVo;
        });
        // 返回 page 对象
        return (Page<AccountDetailVo>) accountDetailVoIPage;
    }
}
